<?php

class Soul_Loader {

	static private $_singletons = array();
	static private $_foundClasses = array();

	static public function loadSingleton($className, array $args = array()) {
		if (!isset(self::$_singletons[$className])) {
			self::$_singletons[$className] = self::loadInstance($className, $args);
		}

		return self::$_singletons[$className];
	}

	static public function loadInstance($className, array $args = array()) {
		$class = self::loadClass($className);
		if (empty($class)) {
			throw new Exception('Not found class [' . $className . ']');
		}

		$className = self::loadClass($className);
		
		$result = NULL;
		$argLen = count($args);
		switch($argLen){
			case 1:
				$result = new $className($args[0]);
				break;
			case 2:
				$result = new $className($args[0], $args[1]);
				break;
			case 3:
				$result = new $className($args[0], $args[1], $args[2]);
				break;
			case 4:
				$result = new $className($args[0], $args[1], $args[2], $args[3]);
				break;
			case 5:
				$result = new $className($args[0], $args[1], $args[2], $args[3], $args[4]);
				break;
			default:
				$result = new $className();
				break;
		}

		if(in_array($className, Soul_Config::$proxyClasses)){
			return new Soul_Classes_Proxy($result);
		}

		return $result;
	}
	
	static public function isInScope($className){
		$arr = explode('_', $className);
		$staticScopes = Soul_Config::$staticScopes;
		$dynamicScopes = Soul_Config::$dynamicScopes;
		if(in_array($arr[0], $staticScopes)){
			return TRUE;
		}
		if(in_array($arr[0], $dynamicScopes)){
			return TRUE;
		}
		return FALSE;
	}	

	static public function loadClass($className) {
		if (self::isInScope($className)) {
			return $className;
		}

		if (isset(self::$_foundClasses[$className])) {
			return self::$_foundClasses[$className];
		}

		$staticScopes = Soul_Config::$staticScopes;
		$dynamicScopes = Soul_Config::$dynamicScopes;
		$dynamicPaths = Soul_Config::$dynamicPaths;
		if (!isset(self::$_foundClasses[$className])) {
			$subPath = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $className))) . '.php';
			foreach ($dynamicScopes as $scope) {
				foreach ($dynamicPaths as $path) {
					if (file_exists($path . $scope . DIRECTORY_SEPARATOR . $subPath)) {
						self::$_foundClasses[$className] = $scope . '_' . $className;
						return $scope . '_' . $className;
					}
				}
			}
		}
		
		return NULL;
	}
}